package com.onepower.core.modules.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.onepower.core.domain.mapper.MatchScheduleInfoMapper;
import com.onepower.core.domain.request.CreateMatchScheduleForm;
import com.onepower.core.domain.request.MatchScheduleQuery;
import com.onepower.core.domain.response.MatchCheckInfo;
import com.onepower.core.domain.response.MatchScheduleInfo;
import com.onepower.core.exception.BizException;
import com.onepower.core.modules.repository.entity.*;
import com.onepower.core.modules.repository.entity.extend.MatchScheduleExtend;
import com.onepower.core.modules.repository.mapper.MatchScheduleMapper;
import com.onepower.core.modules.service.*;
import com.onepower.core.result.BizResultCode;
import com.onepower.core.result.CommonResult;
import com.onepower.core.utils.ExcelUtils;
import com.onepower.core.utils.ResultUtils;
import com.onepower.core.utils.SecurityUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.*;

/**
 * <p>
 * </p>
 *
 * @author kin
 * @since 2018-08-06
 */
@Service
public class MatchScheduleServiceImpl extends ServiceImpl<MatchScheduleMapper, MatchSchedule> implements IMatchScheduleService {


    @Autowired
    private ITkdMatchService tkdMatchService;

    @Autowired
    private IMatchPlaceService matchPlaceService;

    @Autowired
    private IMatchProjectScoreService matchProjectScoreService;

    @Autowired
    private IMatchScheduleTwoService matchScheduleTwoService;

    @Autowired
    private IMatchProjectService matchProjectService;

    @Override
    public CommonResult createScheduleServiceByOnline(List<CreateMatchScheduleForm> forms) throws IOException {

        Integer currentUserId = SecurityUtils.getCurrentUserId();
        for (CreateMatchScheduleForm form : forms) {
            List<MatchSchedule> matchScheduleList = new ArrayList<>();
            MatchPlace matchPlace = matchPlaceService.getById(form.getMatchPlaceId());
            String baseUrl = tkdMatchService.getMatchPullDataUrl(form.getMatchId());
            String scheduleUrl = baseUrl + "/tkd.asp?Action=" + form.getTypeCode() + "&Field=" + matchPlace.getPlaceName() + "&NO=";
            String scoreUrl = baseUrl + "/score.asp?Action=" + form.getTypeCode() + "&Field=" + matchPlace.getPlaceName() + "&NO=";
            for (Integer i = form.getRangeStart(); i <= form.getRangeEnd(); i++) {
                String e = "";
                if (i < 10) {
                    e = "00" + i;
                } else if (i < 99) {
                    e = "0" + i;
                } else if (i >= 100) {
                    e = i.toString();
                }
                String fullUrl = scheduleUrl + i.toString();
                MatchSchedule matchSchedule = getMatchSchedule(fullUrl, form.getMatchType());
                matchSchedule.setMatchId(form.getMatchId());
                matchSchedule.setMatchPlaceId(matchPlace.getId());
                matchSchedule.setType(form.getMatchType());
                matchSchedule.setMatchCode(matchPlace.getPlaceName() + e);
                matchSchedule.setScoreString(scoreUrl + i.toString());
                matchSchedule.setFormalType(true);
                if (form.getIsTwo()) {
                    matchSchedule.setTwoTime(true);
                } else {
                    matchSchedule.setTwoTime(false);
                }
                matchSchedule.setIsShowScore(0);
                matchSchedule.setIsShowRanking(0);
                matchSchedule.setIsCheck(0);
                matchSchedule.setIsComplete(0);
                matchSchedule.setRefereeType(form.getRefereeType());
                matchSchedule.setCreaterId(currentUserId);
                matchSchedule.setCreateTime(new Date());
                matchScheduleList.add(matchSchedule);
            }
            this.saveBatch(matchScheduleList);
        }
        List<MatchSchedule> matchScheduleTwos = baseMapper.selectTwoSchedule(forms.get(0).getMatchId());
        List<MatchScheduleTwo> twoList = new ArrayList<>();
        if (matchScheduleTwos != null && matchScheduleTwos.size() > 0) {
            for (MatchSchedule schedule : matchScheduleTwos) {
                MatchScheduleTwo two = new MatchScheduleTwo();
                two.setMatchScheduleId(schedule.getId());
                two.setFormalType(true);
                twoList.add(two);
            }
        }
        matchScheduleTwoService.saveBatch(twoList);
        return ResultUtils.ok();
    }

    @Override
    public CommonResult createScheduleByImport(Integer matchId, MultipartFile file) throws Exception {
        List<List<Object>> lists = ExcelUtils.importExcel(file.getInputStream(), file.getOriginalFilename());

        TkdMatch match = tkdMatchService.getById(matchId);
        List<MatchPlace> matchPlaces = matchPlaceService.getListByMatchId(matchId);
        List<MatchSchedule> matchSchedules = new ArrayList<>();
        for (List<Object> objs : lists) {
            if (objs.get(0) != null && !StringUtils.isEmpty(objs.get(0).toString())) {
                MatchSchedule schedule = new MatchSchedule();
                schedule.setMatchId(matchId);
                schedule.setFormalType(false);
                MatchPlace place = matchPlaces.stream().filter(x -> objs.get(0).toString().equals(x.getPlaceName()))
                        .findFirst()
                        .orElse(null);
                assert place != null;
                schedule.setMatchPlaceId(place.getId());
                int code = Integer.parseInt(objs.get(1).toString());
                String codeNo = "";
                if (code < 10) {
                    codeNo = "00" + code;
                } else if (code < 99) {
                    codeNo = "0" + code;
                } else if (code >= 100) {
                    codeNo = Integer.toString(code);
                }
                schedule.setMatchCode(place.getPlaceName() + codeNo);
                if (objs.get(2).toString().equals("个人")) {
                    schedule.setType(0);
                } else if (objs.get(2).toString().equals("对阵")) {
                    schedule.setType(1);
                } else if (objs.get(2).toString().equals("对阵")) {
                    schedule.setType(0);
                }
                if (objs.get(11).toString().equals("是")) {
                    schedule.setTwoTime(true);
                }
                schedule.setPsEntry(objs.get(3).toString());
                schedule.setRefereeType(match.getRefereeType());
                schedule.setBlueTeam(objs.get(4).toString());
                schedule.setBluePlayer(objs.get(5).toString());
                schedule.setIsShowRanking(0);
                schedule.setIsShowScore(0);
                schedule.setIsCheck(0);
                schedule.setIsComplete(0);
                schedule.setScheduleName(objs.get(8).toString());
                schedule.setScheduleGroup(objs.get(9).toString());
                schedule.setScheduleLevel(objs.get(10).toString());
                schedule.setCreateTime(new Date());
                schedule.setCreaterId(SecurityUtils.getCurrentUserId());
                matchSchedules.add(schedule);
            }
        }
        this.saveBatch(matchSchedules);
        return ResultUtils.ok();
    }

    public CommonResult updateMatchSchedule(Map map) {

        if (!map.containsKey("matchScheduleId"))
            throw new BizException(9999, "场次ID不能为空");

        MatchSchedule schedule = baseMapper.selectScheduleById(Integer.parseInt(map.get("matchScheduleId").toString()));

        if (map.containsKey("blueTeam"))//青方队名
            schedule.setBlueTeam(map.get("blueTeam").toString());

        if (map.containsKey("bluePlayer"))//青方运动员名称
            schedule.setBluePlayer(map.get("bluePlayer").toString());

        if (map.containsKey("redTeam"))//红方队名
            schedule.setRedTeam(map.get("redTeam").toString());

        if (map.containsKey("redPlayer"))//红方运动员名称
            schedule.setRedPlayer(map.get("redPlayer").toString());

        if (map.containsKey("expressivenessScore"))//表现力总分
            schedule.setExpressivenessScore(Double.parseDouble(map.get("expressivenessScore").toString()));

        if (map.containsKey("accuracyScore"))//准确度总分
            schedule.setAccuracyScore(Double.parseDouble(map.get("accuracyScore").toString()));

        if (map.containsKey("totalScore"))//个人总分
            schedule.setTotalScore(Double.parseDouble(map.get("totalScore").toString()));

        if (map.containsKey("psEntry"))//品势章目
            schedule.setPsEntry(map.get("psEntry").toString());

        if (map.containsKey("isShowScore"))
            schedule.setIsShowScore(1);

        if (map.containsKey("isShowRanking"))
            schedule.setIsShowRanking(1);

        baseMapper.updateById(schedule);
        return ResultUtils.ok();
    }

    @Override
    public MatchScheduleInfo getSchedule(Integer id) {
        MatchScheduleExtend matchScheduleExt = baseMapper.selectScheduleById(id);
        return MatchScheduleInfoMapper.MAPPER.converterExtToInfo(matchScheduleExt);
    }

    @Override
    public Page<MatchScheduleInfo> getScheduleList(Page<MatchScheduleInfo> page, MatchScheduleQuery query) {
        List<MatchScheduleExtend> matchScheduleList = baseMapper.selectScheduleList(page, query);
        List<MatchScheduleInfo> matchScheduleInfoList = MatchScheduleInfoMapper.MAPPER.converterExtToInfoList(matchScheduleList);
        page.setRecords(matchScheduleInfoList);
        return page;
    }

    @Override
    public MatchScheduleInfo getMatchScheduleLockedByReferee(Integer matchId, Integer matchAdminId) {
        List<MatchScheduleExtend> list = baseMapper.selectLockedSchedule(matchId, matchAdminId, 0);

        if (CollectionUtils.isEmpty(list)) {
            return null;
        }

        MatchScheduleInfo matchScheduleInfo = MatchScheduleInfoMapper.MAPPER.converterExtToInfo(list.get(0));
        if (matchScheduleInfo != null) {
            if (matchScheduleInfo.getIsShowScore() == 0) {
                if (matchScheduleInfo.getType() == 1) {
                    matchScheduleInfo.setTotalScore(0d);
                } else {
                    matchScheduleInfo.setTotalScore(99d);
                }
            }
            matchScheduleInfo.setMatchNumber(matchScheduleInfo.getMatchCode().substring(1));
        }

        return matchScheduleInfo;
    }

    @Override
    public List<MatchScheduleInfo> getMultiMatchScheduleLockedByReferee(Integer matchId, Integer matchAdminId) {
        List<MatchScheduleExtend> list = baseMapper.selectLockedSchedule(matchId, matchAdminId, 1);
        return MatchScheduleInfoMapper.MAPPER.converterExtToInfoList(list);
    }

    @Override
    public Page<MatchCheckInfo> getMatchScheduleCheckPage(Page<MatchCheckInfo> page, Integer matchPlaceId) {
        List<MatchScheduleExtend> matchScheduleList = baseMapper.selectScheduleListWithNoCheck(page, matchPlaceId);
        page.setRecords(MatchScheduleInfoMapper.MAPPER.converterExtToCheckInfoList(matchScheduleList));
        return page;
    }

    private String sendGet(String url) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result.toString();
    }

    private MatchSchedule getMatchSchedule(String url, Integer matchType) throws IOException {
        MatchSchedule matchSchedule = new MatchSchedule();
        // Document doc2 = Jsoup.connect("http://www.gz202.com/tqd/tkd.asp?Action=grps&Field=B&NO=1").get();
        Document doc2 = Jsoup.connect(url).header("Accept", "text/html").header("Content-Encoding", "gzip").get();
        Elements infoTable = doc2.body().getElementsByTag("table");
        Elements tableLineInfos = infoTable.select("tr");
        //获取比赛组别
        Element title = tableLineInfos.first();
        String fullNmae = title.select("td").first().text().trim();
        String groupName = title.select("td").first().text().trim().split("/")[0];
        String levelName = title.select("td").first().text().trim().split("/")[1];
        matchSchedule.setScheduleName(fullNmae);
        matchSchedule.setScheduleLevel(levelName);
        matchSchedule.setScheduleGroup(groupName);
        // 获取代表队
        Elements group = tableLineInfos.get(1).select("td");
        matchSchedule.setBlueTeam(group.first().text().trim());
        if (group.size() > 1) {
            matchSchedule.setRedTeam(group.get(2).text().trim());
        }
        //获取运动员名称
        if (matchType == 1) {
            Elements player = tableLineInfos.last().select("td");
            StringBuilder bluePlayer = new StringBuilder();
            for (Element element : player) {
                bluePlayer.append(" ").append(element.text().trim());
            }
            matchSchedule.setBluePlayer(bluePlayer.toString());

        } else {
            Elements player = tableLineInfos.last().select("td");
            matchSchedule.setBluePlayer(player.get(0).text().trim());
            matchSchedule.setRedPlayer(URLDecoder.decode(player.get(2).text().trim(), "gb2312"));
        }

        return matchSchedule;
    }

    private String pullScore(List<MatchScore> scoreList, Integer matchType, String scoreUrl, int matchScheduleId) {
        String scoreStr1 = "";
        String scoreStr2 = "";
        if (matchType == 1) {
            for (MatchScore matchScore : scoreList) {
                scoreStr1 += matchScore.getAccuracy() + "@";
                scoreStr2 += matchScore.getExpressiveness() + "@";
            }
            if (scoreList.size() == 3) {
                scoreStr1 += "0.0@4.0";
                scoreStr2 += "0.0@6.0";
            } else if (scoreList.size() > 3) {
                scoreStr1 = scoreStr1.substring(0, scoreStr1.length() - 1);
                scoreStr2 = scoreStr2.substring(0, scoreStr2.length() - 1);
            }
        }
        if (matchType == 2) {
            Integer k = 0;
            if (scoreList.size() >= 3) {
                List<Integer> intList = new ArrayList<>();
                for (MatchScore matchScore : scoreList) {
                    intList.add(matchScore.getWinner());
                }
                k = getWinner(intList);
            } else {
                k = baseMapper.selectById(matchScheduleId).getWinner();
            }
            if (k == 0) {
                scoreStr1 = "S";
                scoreStr2 = "B";
            }
            if (k == 1) {
                scoreStr1 = "B";
                scoreStr2 = "S";
            }
        }
        String fullUrl = scoreUrl + "&sData=" + scoreStr1 + ":" + scoreStr2 + "&timeStamp&Signature";
        return sendGet(fullUrl);

    }


    private String pullScoreOne(List<MatchScore> scoreList, Integer matchType, String scoreUrl) {
        String scoreStr1 = "";
        String scoreStr2 = "";
        if (matchType.equals(1)) {
            for (MatchScore matchScore : scoreList) {
                scoreStr1 += matchScore.getAccuracy() + "@";
                scoreStr2 += matchScore.getExpressiveness() + "@";
            }
            scoreStr1 = scoreStr1.substring(0, scoreStr1.length() - 1);
            scoreStr2 = scoreStr2.substring(0, scoreStr2.length() - 1);
        }
        if (matchType == 2) {
            Integer k;
            List<Integer> intList = new ArrayList<>();
            for (MatchScore matchScore : scoreList) {
                intList.add(matchScore.getWinner());
            }
            k = getWinner(intList);
            if (k == 0) {
                scoreStr1 = "S";
                scoreStr2 = "B";
            }
            if (k == 1) {
                scoreStr1 = "B";
                scoreStr2 = "S";
            }
        }
        String fullUrl = scoreUrl + "&sData=" + scoreStr1 + ":" + scoreStr2 + "&timeStamp&Signature";
        return sendGet(fullUrl);
    }


    private void getMatchScore(Integer matchId, Integer matchTyp, Boolean multiType, Integer matchScheduleId, Integer refereeType, Boolean isTwoTime) {
        if (multiType) {
            QueryWrapper<MatchProject> sar = new QueryWrapper<MatchProject>();
            sar.eq("match_id", matchId);
            List<MatchProject> projects = matchProjectService.list(sar);

            QueryWrapper<MatchProjectScore> war = new QueryWrapper<MatchProjectScore>();
            war.eq("match_schedule_id", matchScheduleId);

            List<MatchProjectScore> projectScores = matchProjectScoreService.list(war);
            if (projectScores.size() > 0) {
                Map<String,List<MatchProjectScore>> stringListMap =new HashMap<>();
                for (MatchProject project : projects) {

                }

            }
        } else {
        }
    }

    private Integer getWinner(List<Integer> intList) {
        Integer score = 0;
        if (intList.size() == 3) {
            for (Integer k : intList) {
                score += k;
            }
            return score >= 2 ? 1 : 0;
        } else if (intList.size() > 3) {
            for (Integer k : intList) {
                score += k;
            }
            return score - (intList.size() / 2) > 0 ? 1 : 0;
        } else {
            throw new BizException(BizResultCode.MATCH_REFEREE_NOT_RIGHT);
        }
    }

}
